package com.sc.nft.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.config.hf.HfConfig;
import com.sc.nft.config.hna.HnaConfig;
import com.sc.nft.config.lianlian.LlConfig;
import com.sc.nft.config.sand.SandConfig;
import com.sc.nft.config.sand.SandPayUtil;
import com.sc.nft.dao.ExpenditureRecordDao;
import com.sc.nft.dao.MallOrderIncomeDao;
import com.sc.nft.dao.MallOrderRefundDao;
import com.sc.nft.dao.UserInfoDao;
import com.sc.nft.dao.UserWalletDao;
import com.sc.nft.dao.UserWalletDetailDao;
import com.sc.nft.dto.HnaRefundDto;
import com.sc.nft.dto.MallOrderPushDTO;
import com.sc.nft.dto.MallOrderRefundDTO;
import com.sc.nft.entity.ExpenditureRecord;
import com.sc.nft.entity.MallActivityShare;
import com.sc.nft.entity.MallActivityShareTeam;
import com.sc.nft.entity.MallOrder;
import com.sc.nft.entity.MallOrderIncome;
import com.sc.nft.entity.MallOrderProduct;
import com.sc.nft.entity.MallOrderRefund;
import com.sc.nft.entity.MallOrderStatusLog;
import com.sc.nft.entity.MallPayOrderItem;
import com.sc.nft.entity.MallPayOrderRecord;
import com.sc.nft.entity.MallShareTeamOrder;
import com.sc.nft.entity.UserCreatorInfo;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.UserWallet;
import com.sc.nft.entity.UserWalletDetail;
import com.sc.nft.entity.dto.AdminPageRefundOrderDTO;
import com.sc.nft.entity.dto.RefundOrderLogDTO;
import com.sc.nft.enums.ExpenditureRecordTypeEnum;
import com.sc.nft.enums.MallOrderIncomeTypeEnum;
import com.sc.nft.enums.MallOrderPushTypeEnum;
import com.sc.nft.enums.MallOrderRefundStatusEnum;
import com.sc.nft.enums.MallOrderRefundTypeEnum;
import com.sc.nft.enums.MallOrderStatusEnum;
import com.sc.nft.enums.MallRefundStatusEnum;
import com.sc.nft.enums.PayMethodEnum;
import com.sc.nft.enums.PayStatusEnum;
import com.sc.nft.enums.PayTypeEnum;
import com.sc.nft.enums.SourceEnum;
import com.sc.nft.enums.UserBalanceTypeEnum;
import com.sc.nft.enums.WalletDetailTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.feign.WxMiniPayClient;
import com.sc.nft.helper.HfPayHelper;
import com.sc.nft.helper.HnaPayHelper;
import com.sc.nft.helper.LlPayHelper;
import com.sc.nft.helper.SmartSupplyHelper;
import com.sc.nft.req.wxPay.WxRefundReq;
import com.sc.nft.service.MallActivityShareService;
import com.sc.nft.service.MallActivityShareTeamService;
import com.sc.nft.service.MallOrderProductService;
import com.sc.nft.service.MallOrderPushService;
import com.sc.nft.service.MallOrderRefundService;
import com.sc.nft.service.MallOrderRefundStatusLogService;
import com.sc.nft.service.MallOrderService;
import com.sc.nft.service.MallPayOrderItemService;
import com.sc.nft.service.MallPayOrderRecordService;
import com.sc.nft.service.MallShareTeamOrderService;
import com.sc.nft.service.MallUserActivityRankingDetailService;
import com.sc.nft.service.MallUserPropsRewardsDetailService;
import com.sc.nft.service.UserCreatorInfoService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.Result;
import com.sc.nft.util.BigDecimalUtils;
import com.sc.nft.util.OrderNoUtil;
import com.sc.nft.vo.wxPay.Refund;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 售后业务层实现
 *
 * @author liGen
 * @version 1.0
 * @date 2023/11/18 3:47 下午
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class MallOrderRefundServiceImpl implements MallOrderRefundService {

    private final MallOrderRefundDao mallOrderRefundDao;
    private final MallOrderProductService mallOrderProductService;
    private final MallOrderRefundStatusLogService mallOrderRefundStatusLogService;
    private final UserCreatorInfoService userCreatorInfoService;
    private final MallPayOrderRecordService mallPayOrderRecordService;
    private final HfPayHelper hfPayHelper;
    private final LlPayHelper llPayHelper;
    private final HnaConfig hnaConfig;
    private final HnaPayHelper hnaPayHelper;
    private final UserInfoDao userInfoDao;
    private final UserWalletDao userWalletDao;
    private final UserWalletDetailDao userWalletDetailDao;
    private final ExpenditureRecordDao expenditureRecordDao;
    private final SmartSupplyHelper smartSupplyHelper;
    private final MallOrderIncomeDao mallOrderIncomeDao;
    private final MallActivityShareService mallActivityShareService;
    private final MallActivityShareTeamService mallActivityShareTeamService;
    private final MallPayOrderItemService mallPayOrderItemService;
    private final WxMiniPayClient wxMiniPayClient;
    private final MallOrderPushService mallOrderPushService;
    private final MallUserActivityRankingDetailService mallUserActivityRankingDetailService;
    private final MallUserPropsRewardsDetailService mallUserPropsRewardsDetailService;
    @Autowired
    MallOrderService mallOrderService;

    @Autowired
    MallShareTeamOrderService mallShareTeamOrderService;

    /**
     * 获取订单的有效金额售后订单
     *
     * @param orderId
     * @return
     */
    @Override
    public List<MallOrderRefund> getAmountInForceListByOrderId(Long orderId) {
        return mallOrderRefundDao.getAmountInForceListByOrderId(orderId);
    }

    /**
     * 订单是否存在售后中的售后单
     *
     * @param orderId
     * @return
     */
    @Override
    public Boolean whetherTheAfterSalesOrderExists(Long orderId) {
        return mallOrderRefundDao.whetherTheAfterSalesOrderExists(orderId);
    }

    /**
     * 获取订单下的所有售后订单
     *
     * @param orderId
     * @return
     */
    @Override
    public List<MallOrderRefundDTO> getRefundListByOrderId(Long orderId) {
        return mallOrderRefundDao.getRefundListByOrderId(orderId);
    }

    /**
     * 获取售后详情
     *
     * @param id
     * @return
     */
    @Override
    public MallOrderRefundDTO getDetailsById(Long id) {
        MallOrderRefundDTO details = mallOrderRefundDao.getDetailsById(id);
        MallOrder mallOrder = mallOrderService.getById(details.getOrderId());
        details.setDaoId(mallOrder.getDaoId());
        //客服微信
        UserCreatorInfo userCreatorInfo = userCreatorInfoService.getById(details.getDaoId());
        if (Objects.nonNull(userCreatorInfo)) {
            details.setCustomerServiceUrl(ObjectUtil.isNull(userCreatorInfo.getCustomerServiceUrl()) ? StrUtil.EMPTY : userCreatorInfo.getCustomerServiceUrl());
        }
        return details;
    }

    /**
     * 获取售后
     *
     * @param id
     * @return
     */
    @Override
    public MallOrderRefund getById(Long id) {
        MallOrderRefund orderRefund = mallOrderRefundDao.getById(id);
        Assert.notNull(orderRefund, () -> new GlobalRunTimeException(ErrorCode.THE_AFTER_SALES_ORDER_DOES_NOT_EXIST));
        return orderRefund;
    }

    /**
     * 取消售后
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelAfterSale(Long id) {
        // 售后订单
        MallOrderRefund mallOrderRefund = getById(id);
        // 售后状态判断是否可以取消售后
        Assert.isTrue(MallRefundStatusEnum.cancelStatusList().contains(mallOrderRefund.getRefundStatus()), () -> new GlobalRunTimeException(ErrorCode.THIS_ORDER_CANNOT_BE_CANCELLED_AFTER_SALE));
        Long orderId = mallOrderRefund.getOrderId();
        MallOrder mallOrder = mallOrderService.getById(orderId);
        Assert.notNull(mallOrder, () -> new GlobalRunTimeException(ErrorCode.MALL_ORDER_DOES_NOT_EXIST));
        // 订单商品
        MallOrderProduct mallOrderProduct = mallOrderProductService.getById(mallOrderRefund.getOrderGoodsId());
        Assert.notNull(mallOrderProduct, () -> new GlobalRunTimeException(ErrorCode.MALL_ORDER_PRODUCT_DOES_NOT_EXIST));
        mallOrderRefund.setRefundStatus(MallRefundStatusEnum.CANCEL);
        mallOrderRefund.updateById();
        // 还原订单商品售后数量
        Integer refundNum = mallOrderProduct.getRefundNum();
        mallOrderProduct.setRefundNum(refundNum - mallOrderRefund.getRefundNum());
        mallOrderProduct.setRefundPrice(BigDecimalUtils.subtract(mallOrderProduct.getRefundPrice(), mallOrderRefund.getRefundAmount()));
        mallOrderProduct.updateById();
        // 售后单操作日志记录
        mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.CANCEL, MallRefundStatusEnum.CANCEL.getDescription());
        // 判断是否存在售后单
        Boolean afterSalesOrderExists = whetherTheAfterSalesOrderExists(orderId);
        if (!afterSalesOrderExists) {
            mallOrder.setRefundStatus(MallOrderRefundStatusEnum.NEW_NOT_APPLY);
            mallOrder.updateById();
        } else {
            mallOrder.setRefundPrice(BigDecimalUtils.subtract(mallOrder.getRefundPrice(), mallOrderRefund.getRefundAmount()));
            mallOrder.updateById();
        }
    }

    /**
     * 用户退货填写快递(编辑退货物流)
     *
     * @param id               售后单
     * @param userDeliveryNo   用户快递单号
     * @param userDeliveryName 用户快递名称
     * @return
     */
    @Override
    public void userReturn(Long id, String userDeliveryNo, String userDeliveryName) {
        MallOrderRefund mallOrderRefund = getById(id);
        if (MallOrderRefundTypeEnum.getUsersCanReturnGoodsList().contains(mallOrderRefund.getRefundType()) && MallRefundStatusEnum.TO_BE_RETURNED == mallOrderRefund.getRefundStatus()) {
            mallOrderRefund.setUserDeliveryNo(userDeliveryNo);
            mallOrderRefund.setUserDeliveryName(userDeliveryName);
            mallOrderRefund.setRefundStatus(MallRefundStatusEnum.RETURNING_GOODS);
            mallOrderRefund.updateById();
            mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.RETURNING_GOODS, MallRefundStatusEnum.RETURNING_GOODS.getDescription());
        } else {
            new GlobalRunTimeException(ErrorCode.THIS_ORDER_CANNOT_BE_RETURNED);
        }
    }

    /**
     * 获取用户下的所有售后订单
     *
     * @param userId
     * @return
     */
    @Override
    public Page<MallOrderRefundDTO> getRefundListByUserId(Long userId, Integer pageNo, Integer pageSize) {
        return mallOrderRefundDao.getRefundListByUserId(userId, new Page<>(pageNo, pageSize));
    }

    /**
     * 管理后台售后列表
     *
     * @param pageNo
     * @param pageSize
     * @param orderNo
     * @param refundNo
     * @param refundStatus
     * @param refundType
     * @param userTel
     * @return
     */
    @Override
    public Page<AdminPageRefundOrderDTO> getAdminPageRefundOrderDTO(Integer pageNo, Integer pageSize, String orderNo, String refundNo, Integer refundStatus, Integer refundType, String userTel) {
        return mallOrderRefundDao.getAdminPageRefundOrderDTO(pageNo, pageSize, orderNo, refundNo, refundStatus, refundType, userTel);
    }

    /**
     * 管理后台售后详情
     *
     * @param id
     * @return
     */
    @Override
    public AdminPageRefundOrderDTO getAdminRefundOrderDTO(Long id) {
        return mallOrderRefundDao.getAdminRefundOrderDTO(id);
    }

    /**
     * 通过售后编号获取售后单
     *
     * @param refundNo 售后编号
     * @return
     */
    @Override
    public MallOrderRefund getByNo(String refundNo) {
        return mallOrderRefundDao.getByNo(refundNo);
    }

    /**
     * 获取订单的退款成功的售后订单
     *
     * @param orderId
     * @return
     */
    @Override
    public List<MallOrderRefund> getRefundSuccessListByOrderId(Long orderId) {
        return mallOrderRefundDao.getRefundSuccessListByOrderId(orderId);
    }

    /**
     * 售后单自动取消  待退货状态
     *
     * @param day
     */
    @Override
    public void theAfterSalesOrderIsAutomaticallyCancelled(Integer day) {
        // 获取待退货售后单的操作时间
        List<RefundOrderLogDTO> refundOrderLogDTOList = mallOrderRefundDao.getRefundOrderLogDTOList(MallRefundStatusEnum.TO_BE_RETURNED.getCode(), MallRefundStatusEnum.TO_BE_RETURNED.toString());
        for (RefundOrderLogDTO refundOrderLogDTO : refundOrderLogDTOList) {
            try {
                Date logTime = refundOrderLogDTO.getLogTime();
                DateTime dateTime = DateUtil.offsetDay(logTime, day);
                if (DateTime.now().isAfter(dateTime)) {
                    //售后单取消
                    cancelAfterSale(refundOrderLogDTO.getId());
                }
            } catch (Exception e) {
                log.error("售后单自动取消异常 refundOrderId:{}", refundOrderLogDTO.getId(), e);
            }
        }
    }

    /**
     * 售后单自动换货完成  换货待收
     *
     * @param day
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void afterSaleOrderAutomaticReplacementCompleted(Integer day) {
        // 获取换货待收售后单的操作时间
        log.info("自动换货 开始 day:" + day);
        List<RefundOrderLogDTO> refundOrderLogDTOList = mallOrderRefundDao.getRefundOrderLogDTOList(MallRefundStatusEnum.REPLACEMENT_TO_BE_RECEIVED.getCode(), MallRefundStatusEnum.REPLACEMENT_TO_BE_RECEIVED.toString());
        log.info("自动换货 refundOrderLogDTOList:" + JSON.toJSONString(refundOrderLogDTOList));
        for (RefundOrderLogDTO refundOrderLogDTO : refundOrderLogDTOList) {
            try {
                Date logTime = refundOrderLogDTO.getLogTime();
                log.info("自动换货 logTime:" + logTime);
                DateTime dateTime = DateUtil.offsetDay(logTime, day);
                log.info("自动换货 dateTime:" + dateTime);
                if (DateTime.now().isAfter(dateTime)) {
                    //售后单自动换货完成
                    log.info("自动换货 售后单自动换货完成");
                    MallOrderRefund mallOrderRefund = new MallOrderRefund();
                    mallOrderRefund.setId(refundOrderLogDTO.getId());
                    mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REPLACEMENT_COMPLETED);
                    mallOrderRefundDao.updateById(mallOrderRefund);
                    log.info("自动换货 售后单操作日志");
                    // 售后单操作日志
                    mallOrderRefundStatusLogService.create(refundOrderLogDTO.getId(), MallRefundStatusEnum.REPLACEMENT_COMPLETED, MallRefundStatusEnum.REPLACEMENT_COMPLETED.getDescription());
                    log.info("自动换货 处理订单商品退款状态");
                    //处理订单商品退款状态
                    MallOrderProduct mallOrderProduct = mallOrderProductService.getById(refundOrderLogDTO.getOrderGoodsId());
                    mallOrderProduct.setRefundSuccessCount(mallOrderProduct.getRefundSuccessCount() + refundOrderLogDTO.getRefundNum());
                    mallOrderProduct.updateById();
                    log.info("自动换货 推送消息 开始");
                    //region 推送消息
                    MallOrderPushDTO mallOrderPushDTO = new MallOrderPushDTO();
                    mallOrderPushDTO.setMallOrderRefund(mallOrderRefundDao.getById(refundOrderLogDTO.getId()));
                    mallOrderPushDTO.setMallOrderProduct(mallOrderProduct);
                    mallOrderPushService.mallOrderPushMessage(mallOrderPushDTO, MallOrderPushTypeEnum.AUTO_REPLACE_COMPLETE);
                    log.info("自动换货 推送消息 结束");
                    //endregion
                }
            } catch (Exception e) {
                log.error("售后单自动换货完成异常 refundOrderId:{},orderGoodsId:{}", refundOrderLogDTO.getId(), refundOrderLogDTO.getOrderGoodsId(), e);
            }
        }
    }

    /**
     * 售后单自动同意  申请中
     *
     * @param day
     */
    @Override
    public void afterSalesOrderAutomaticallyAgreed(Integer day) {
        // 获取申请中售后单的操作时间
        List<RefundOrderLogDTO> refundOrderLogDTOList = mallOrderRefundDao.getRefundOrderLogDTOList(MallRefundStatusEnum.APPLYING.getCode(), MallRefundStatusEnum.APPLYING.toString());
        for (RefundOrderLogDTO refundOrderLogDTO : refundOrderLogDTOList) {
            try {
                Date logTime = refundOrderLogDTO.getLogTime();
                DateTime dateTime = DateUtil.offsetDay(logTime, day);
                if (DateTime.now().isAfter(dateTime)) {
                    Integer refundStatus = null;
                    if (MallOrderRefundTypeEnum.ONLY_REFUND == refundOrderLogDTO.getRefundType()) {
                        // 仅退款
                        refundStatus = MallRefundStatusEnum.REFUNDING.getCode();
                    } else if (MallOrderRefundTypeEnum.REFUNDS == refundOrderLogDTO.getRefundType() || MallOrderRefundTypeEnum.EXCHANGE == refundOrderLogDTO.getRefundType()) {
                        // 退货退款
                        refundStatus = MallRefundStatusEnum.TO_BE_RETURNED.getCode();
                    } else {
                        throw new GlobalRunTimeException("售后单类型异常");
                    }
                    //售后单同意
                    approvalRefund(refundOrderLogDTO.getId(), refundStatus, "127.0.0.1", "", null, null, true);
                }
            } catch (Exception e) {
                log.error("售后单自动同意异常 refundOrderId:{}", refundOrderLogDTO.getId(), e);
            }
        }
    }

    /**
     * 售后单变更
     *
     * @param id               售后单ID
     * @param mallRefundStatus 售后单状态
     * @param ip               请求ip
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approvalRefund(Long id, int mallRefundStatus, String ip, String remark, String deliveryName, String deliveryNo, Boolean isAuto) {
        // 获取售后订单
        MallOrderRefund mallOrderRefund = getById(id);
        // 获取售后单状态
        MallRefundStatusEnum refundStatus = mallOrderRefund.getRefundStatus();
        if (MallRefundStatusEnum.REFUNDING.getCode() == mallRefundStatus) {
            // 售后单状态 -> 待退款
            Boolean canRefund = false;
            MallOrderPushTypeEnum mallOrderPushTypeEnum = null;
            if (MallOrderRefundTypeEnum.ONLY_REFUND == mallOrderRefund.getRefundType() && MallRefundStatusEnum.APPLYING == refundStatus) {
                // 仅退款时申请中可变为待退款
                canRefund = true;
                if (isAuto) {
                    mallOrderPushTypeEnum = MallOrderPushTypeEnum.ONLY_REFUND_AUTO_APPROVAL;
                } else {
                    mallOrderPushTypeEnum = MallOrderPushTypeEnum.ONLY_REFUND_DAO_APPROVAL;
                }
            } else if (MallOrderRefundTypeEnum.REFUNDS == mallOrderRefund.getRefundType() && MallRefundStatusEnum.RETURNING_GOODS == refundStatus) {
                // 退货退款
                canRefund = true;
            }
            if (canRefund) {
                mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUNDING);
                mallOrderRefund.updateById();
                // 售后单操作日志
                mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUNDING, "等待到账，退款金额原路退回");
                //region 推送消息
                if (Objects.nonNull(mallOrderPushTypeEnum)) {
                    MallOrderPushDTO mallOrderPushDTO = new MallOrderPushDTO();
                    mallOrderPushDTO.setMallOrderRefund(mallOrderRefund);
                    mallOrderPushService.mallOrderPushMessage(mallOrderPushDTO, mallOrderPushTypeEnum);
                }
                //endregion
                // 调用退钱
                refund(id, ip);
            }
        } else if (MallRefundStatusEnum.REFUSE_REFUND.getCode() == mallRefundStatus) {
            if (MallRefundStatusEnum.APPLYING != refundStatus) {
                throw new GlobalRunTimeException(ErrorCode.THE_STATUS_OF_THE_AFTER_SALES_ORDER_IS_ABNORMAL);
            }
            // 售后单状态 -> 已拒绝
            mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUSE_REFUND);
            mallOrderRefund.setRemark(remark);
            mallOrderRefund.updateById();
            MallOrderProduct mallOrderProduct = mallOrderProductService.getById(mallOrderRefund.getOrderGoodsId());
            // 还原订单商品售后数量
            Integer refundNum = mallOrderProduct.getRefundNum();
            mallOrderProduct.setRefundNum(refundNum - mallOrderRefund.getRefundNum());
            mallOrderProduct.setRefundPrice(BigDecimalUtils.subtract(mallOrderProduct.getRefundPrice(), mallOrderRefund.getRefundAmount()));
            mallOrderProduct.updateById();
            // 售后单操作日志记录
            mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUSE_REFUND, MallRefundStatusEnum.REFUSE_REFUND.getDescription());
            // 判断是否存在售后单
            List<MallOrderRefund> refundList = getAmountInForceListByOrderId(mallOrderRefund.getOrderId());
            MallOrder mallOrder = mallOrderService.getById(mallOrderRefund.getOrderId());
            if (CollectionUtils.isEmpty(refundList)) {
                mallOrder.setRefundStatus(MallOrderRefundStatusEnum.NEW_NOT_APPLY);
                mallOrder.updateById();
            } else {
                mallOrder.setRefundPrice(BigDecimalUtils.subtract(mallOrder.getRefundPrice(), mallOrderRefund.getRefundAmount()));
                mallOrder.updateById();
            }
            //region 推送消息
            MallOrderPushTypeEnum mallOrderPushTypeEnum = null;
            if (MallOrderRefundTypeEnum.ONLY_REFUND == mallOrderRefund.getRefundType()) {
                mallOrderPushTypeEnum = MallOrderPushTypeEnum.ONLY_REFUND_DAO_REFUND;
            } else if (MallOrderRefundTypeEnum.REFUNDS == mallOrderRefund.getRefundType()) {
                mallOrderPushTypeEnum = MallOrderPushTypeEnum.REFUNDS_DAO_REFUND;
            } else if (MallOrderRefundTypeEnum.EXCHANGE == mallOrderRefund.getRefundType()) {
                mallOrderPushTypeEnum = MallOrderPushTypeEnum.EXCHANGE_DAO_REFUND;
            }
            if (Objects.nonNull(mallOrderPushTypeEnum)) {
                MallOrderPushDTO mallOrderPushDTO = new MallOrderPushDTO();
                mallOrderPushDTO.setMallOrderRefund(mallOrderRefund);
                mallOrderPushService.mallOrderPushMessage(mallOrderPushDTO, mallOrderPushTypeEnum);
            }
            //endregion
        } else if (MallRefundStatusEnum.TO_BE_RETURNED.getCode() == mallRefundStatus) {
            // 售后单状态 -> 待退货
            Boolean can = false;
            MallOrderPushTypeEnum mallOrderPushTypeEnum = null;
            if (MallOrderRefundTypeEnum.REFUNDS == mallOrderRefund.getRefundType() && MallRefundStatusEnum.APPLYING == refundStatus) {
                // 退货退款
                can = true;
                if (isAuto) {
                    mallOrderPushTypeEnum = MallOrderPushTypeEnum.REFUNDS_AUTO_APPROVAL;
                } else {
                    mallOrderPushTypeEnum = MallOrderPushTypeEnum.REFUNDS_DAO_APPROVAL;
                }
            } else if (MallOrderRefundTypeEnum.EXCHANGE == mallOrderRefund.getRefundType() && MallRefundStatusEnum.APPLYING == refundStatus) {
                // 换货
                can = true;
                if (!isAuto) {
                    mallOrderPushTypeEnum = MallOrderPushTypeEnum.EXCHANGE_DAO_APPROVAL;
                }
            }
            if (can) {
                // 售后单状态 -> 待退货
                mallOrderRefund.setRefundStatus(MallRefundStatusEnum.TO_BE_RETURNED);
                mallOrderRefund.updateById();
                // 售后单操作日志记录
                mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.TO_BE_RETURNED, MallRefundStatusEnum.TO_BE_RETURNED.getDescription());
                //region 推送消息
                if (Objects.nonNull(mallOrderPushTypeEnum)) {
                    MallOrderPushDTO mallOrderPushDTO = new MallOrderPushDTO();
                    mallOrderPushDTO.setMallOrderRefund(mallOrderRefund);
                    mallOrderPushService.mallOrderPushMessage(mallOrderPushDTO, mallOrderPushTypeEnum);
                }
                //endregion
            }
        } else if (MallRefundStatusEnum.EXCHANGING_GOODS.getCode() == mallRefundStatus) {
            // 售后单状态 -> 换货中
            Boolean can = false;
            if (MallOrderRefundTypeEnum.EXCHANGE == mallOrderRefund.getRefundType() && MallRefundStatusEnum.RETURNING_GOODS == refundStatus) {
                // 换货
                can = true;
            }
            if (can) {
                // 售后单状态 -> 待退货
                mallOrderRefund.setRefundStatus(MallRefundStatusEnum.EXCHANGING_GOODS);
                mallOrderRefund.updateById();
                // 售后单操作日志记录
                mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.EXCHANGING_GOODS, MallRefundStatusEnum.EXCHANGING_GOODS.getDescription());
            }
        } else if (MallRefundStatusEnum.REPLACEMENT_TO_BE_RECEIVED.getCode() == mallRefundStatus) {
            // 售后单状态 -> 换货待收
            Boolean can = false;
            if (MallOrderRefundTypeEnum.EXCHANGE == mallOrderRefund.getRefundType() && MallRefundStatusEnum.EXCHANGING_GOODS == refundStatus) {
                // 换货
                can = true;
            }
            if (can) {
                // 售后单状态 -> 换货待收
                mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REPLACEMENT_TO_BE_RECEIVED);
                mallOrderRefund.setDeliveryName(deliveryName);
                mallOrderRefund.setDeliveryNo(deliveryNo);
                mallOrderRefund.updateById();
                // 售后单操作日志记录
                mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REPLACEMENT_TO_BE_RECEIVED, MallRefundStatusEnum.REPLACEMENT_TO_BE_RECEIVED.getDescription());
                //region 推送消息
                MallOrderPushTypeEnum mallOrderPushTypeEnum = MallOrderPushTypeEnum.EXCHANGE_DAO_SHIP;
                MallOrderPushDTO mallOrderPushDTO = new MallOrderPushDTO();
                mallOrderPushDTO.setMallOrderRefund(mallOrderRefund);
                mallOrderPushService.mallOrderPushMessage(mallOrderPushDTO, mallOrderPushTypeEnum);
                //endregion
            }
        }
    }

    /**
     * 退款
     *
     * @param oderRefundId 售后单ID
     * @param ip           ip地址
     */
    public void refund(Long oderRefundId, String ip) {
        MallOrderRefund mallOrderRefund = getById(oderRefundId);
        Assert.notNull(mallOrderRefund, () -> new GlobalRunTimeException(ErrorCode.THE_AFTER_SALES_ORDER_DOES_NOT_EXIST));
        // 售后单退款金额
        BigDecimal mallOrderRefundRefundAmount = mallOrderRefund.getRefundAmount();
        BigDecimal orderPayAmount = mallOrderRefund.getOrderPayAmount();
        Assert.isTrue(MallRefundStatusEnum.REFUNDING == mallOrderRefund.getRefundStatus(), () -> new GlobalRunTimeException(ErrorCode.THIS_ORDER_STATUS_IS_NOT_REFUNDABLE));
        MallOrder mallOrder = mallOrderService.getById(mallOrderRefund.getOrderId());
        Assert.notNull(mallOrder, () -> new GlobalRunTimeException(ErrorCode.MALL_ORDER_DOES_NOT_EXIST));
        // 获取订单商品
        MallOrderProduct mallOrderProduct = mallOrderProductService.getById(mallOrderRefund.getOrderGoodsId());
        Assert.notNull(mallOrderProduct, () -> new GlobalRunTimeException(ErrorCode.MALL_ORDER_PRODUCT_DOES_NOT_EXIST));
        MallPayOrderRecord oldPayOrderRecord = null;
        // 获取订单支付记录
        if (mallOrder.getOrderSource() == SourceEnum.META_APP) {
            oldPayOrderRecord = mallPayOrderRecordService.getNewPaySuccessByOrderNo(mallOrder.getOrderNo());
        } else {
            MallPayOrderItem mallPayOrderItem = mallPayOrderItemService.getByOrderId(mallOrder.getId());
            oldPayOrderRecord = mallPayOrderRecordService.getPaySuccessById(mallPayOrderItem.getPayOrderId());
        }
        // 新建退款支付记录
        MallPayOrderRecord newPayOrderRecord = new MallPayOrderRecord();
        newPayOrderRecord.setOrderType(PayTypeEnum.REFUND);
        newPayOrderRecord.setReqTime(DateTime.now());
        newPayOrderRecord.setOrderNo(mallOrder.getOrderNo());
        // 售后单号
        newPayOrderRecord.setRefundNo(mallOrderRefund.getRefundNo());
        newPayOrderRecord.setUserId(mallOrder.getUserId());
        newPayOrderRecord.setPayAmount(mallOrder.getRealPrice());
        // 退款金额
        newPayOrderRecord.setRefundAmount(mallOrderRefundRefundAmount);
        newPayOrderRecord.setChannel(oldPayOrderRecord.getChannel());
        newPayOrderRecord.setStatus(PayStatusEnum.INIT);
        newPayOrderRecord.setTradeNo(UUID.fastUUID().toString().replaceAll("-", ""));
        newPayOrderRecord.setCloseTime(DateUtil.offsetDay(DateTime.now(), 3));
        newPayOrderRecord.setReqIp(ip);
        String result = null;
        if (oldPayOrderRecord.getPayType() == PayMethodEnum.FAST_PAY || oldPayOrderRecord.getPayType() == PayMethodEnum.SAND_BALANCE_PAY) {
            //杉德
            //退款回调地址
            newPayOrderRecord.setNotifyUrl(SandConfig.MALL_REFUND_NOTIFY_URL);
            newPayOrderRecord.setPayType(PayMethodEnum.FAST_PAY);
            JSONObject jsonObject = SandPayUtil.refundRequest(newPayOrderRecord, oldPayOrderRecord.getTradeNo(), mallOrderRefund.getReason());
            newPayOrderRecord.setReqResult(jsonObject.toJSONString());
            if (!StrUtil.equals(jsonObject.getJSONObject("head").getString("respCode"), "000000")) {
                throw new GlobalRunTimeException("退款失败:" + jsonObject.getJSONObject("head").getString("respMsg"));
            }
            mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUNDING);
            mallOrderRefund.updateById();
            // 售后单操作日志
            mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUNDING, "等待到账，退款金额原路退回");
        } else if (oldPayOrderRecord.getPayType() == PayMethodEnum.HF_FAST_PAY) {
            //汇付
            JSONObject refund = hfPayHelper.refund(newPayOrderRecord.getUserId(), oldPayOrderRecord.getTradeNo(), newPayOrderRecord.getTradeNo(), oldPayOrderRecord.getPayTime(), newPayOrderRecord.getRefundAmount(), null, null);
            newPayOrderRecord.setReqResult(refund.toJSONString());
            newPayOrderRecord.setNotifyUrl(HfConfig.mallRefundNotifyUrl);
            newPayOrderRecord.setPayType(PayMethodEnum.HF_FAST_PAY);
            mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUNDING);
            mallOrderRefund.updateById();
            // 售后单操作日志
            mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUNDING, "等待到账，退款金额原路退回");

        } else if (oldPayOrderRecord.getPayType() == PayMethodEnum.LL_PAY) {
            //连连
            UserInfo user = userInfoDao.getById(newPayOrderRecord.getUserId());
            String amount = newPayOrderRecord.getRefundAmount().setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
            JSONObject refund = llPayHelper.refundMall(user, oldPayOrderRecord.getTradeNo(), OrderNoUtil.getOrderNo(), amount, LlConfig.mallLlRefundNotifyUrl);
            newPayOrderRecord.setReqResult(refund.toJSONString());
            newPayOrderRecord.setNotifyUrl(LlConfig.mallLlRefundNotifyUrl);
            newPayOrderRecord.setPayType(PayMethodEnum.LL_PAY);
            newPayOrderRecord.setTradeNo(refund.getString("accp_txno"));
            mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUNDING);
            mallOrderRefund.updateById();
            // 售后单操作日志
            mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUNDING, "等待到账，退款金额原路退回");
        } else if (oldPayOrderRecord.getPayType() == PayMethodEnum.HNA_PAY) {
            UserInfo user = userInfoDao.getById(newPayOrderRecord.getUserId());
            String amount = newPayOrderRecord.getRefundAmount().setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
            HnaRefundDto dto = new HnaRefundDto();
            dto.setRefundAmount(amount);
            dto.setRemark("商场退款");
            dto.setOrgMerOrderId(oldPayOrderRecord.getTradeNo());
            dto.setOrgSubmitTime(DateUtil.format(oldPayOrderRecord.getPayTime(), "yyyyMMddHHmmss"));
            dto.setOrderAmount(mallOrder.getPayPrice().toString());
            if (BigDecimalUtils.eq(orderPayAmount, amount)) {
                dto.setRefundType("1");
            } else {
                dto.setRefundType("2");
            }
            JSONObject refund = hnaPayHelper.refund(user, dto);
            newPayOrderRecord.setReqResult(refund.toJSONString());
            newPayOrderRecord.setNotifyUrl(hnaConfig.getT005NotifyUrl());
            newPayOrderRecord.setPayType(PayMethodEnum.HNA_PAY);
            newPayOrderRecord.setTradeNo(refund.getString("ncountOrderId"));
            mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUNDING);
            mallOrderRefund.updateById();
            // 售后单操作日志
            mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUNDING, "等待到账，退款金额原路退回");
        } else if (oldPayOrderRecord.getPayType() == PayMethodEnum.WX_PAY) {
            // 微信退款
            WxRefundReq wxRefundReq = new WxRefundReq();
            wxRefundReq.setMiniUserId(mallOrder.getMiniUserId());
            wxRefundReq.setTransactionId(oldPayOrderRecord.getWxTransactionId());
            wxRefundReq.setOutTradeNo(oldPayOrderRecord.getOutTradeNo());
            wxRefundReq.setOutRefundNo(newPayOrderRecord.getTradeNo());
            wxRefundReq.setReason(mallOrderRefund.getReason());
            wxRefundReq.setRefundAmount(newPayOrderRecord.getRefundAmount().multiply(new BigDecimal(100)).setScale(0).longValue());
            wxRefundReq.setTotalAmount(oldPayOrderRecord.getPayAmount().multiply(new BigDecimal(100)).setScale(0).longValue());
            Result<Refund> refundResult = wxMiniPayClient.refund(wxRefundReq);
            if (!ErrorCode.SUCCESS.getCode().equals(refundResult.getCode())) {
                throw new GlobalRunTimeException("系统繁忙，请稍后再试！");
            }
            Refund refund = refundResult.getData();
            newPayOrderRecord.setReqResult(JSON.toJSONString(wxRefundReq));
            newPayOrderRecord.setNotifyUrl("");
            newPayOrderRecord.setPayType(PayMethodEnum.WX_PAY);
            newPayOrderRecord.setWxTransactionId(refund.getTransactionId());

            mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUNDING);
            mallOrderRefund.updateById();

            // 售后单操作日志
            mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUNDING, "等待到账，退款金额原路退回");

        } else if (oldPayOrderRecord.getPayType() == PayMethodEnum.WALLET_PAY) {
            // 获取退款成功的退款金额
            List<MallOrderRefund> refundSuccessList = mallOrderRefundDao.getRefundSuccessListByOrderId(mallOrder.getId());
            // 已成功退款数量
            Integer refundSuccessNum = refundSuccessList.stream().mapToInt(MallOrderRefund::getRefundNum).sum();
            BigDecimal refundSuccessAmount = refundSuccessList.stream().map(MallOrderRefund::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            //钱包支付
            UserWallet userWallet = userWalletDao.getByUserId(mallOrder.getUserId());
            newPayOrderRecord.setPayType(PayMethodEnum.WALLET_PAY);
            newPayOrderRecord.setNotifyUrl(SandConfig.FAST_RETURN_URL);
            newPayOrderRecord.setCloseTime(DateTime.now());
            BigDecimal refundWalletBalancePrice = BigDecimal.ZERO;
            BigDecimal refundWalletPrice = BigDecimal.ZERO;
            BigDecimal refundBalancePrice = BigDecimal.ZERO;
            BigDecimal refundWishBalancePrice = BigDecimal.ZERO;
            if (mallOrder.getPayWalletPrice().compareTo(BigDecimal.ZERO) == 1) {
                // 计算余额支付金额退款金额
                if (mallOrderRefund.getRefundNum() + mallOrderProduct.getRefundSuccessCount() >= mallOrderProduct.getProductNum()) {
                    // 计算退款差值
                    // 已成功退款 余额金额
                    BigDecimal refundPayWalletSuccessAmount = refundSuccessList.stream().map(MallOrderRefund::getRefundPayWalletPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                    refundWalletPrice = BigDecimalUtils.subtract(mallOrder.getPayWalletPrice(), refundPayWalletSuccessAmount);
                } else {
                    // 计算退款
                    refundWalletPrice = BigDecimalUtils.multiplys(mallOrder.getPayWalletPrice(), BigDecimalUtils.divide(mallOrderRefundRefundAmount, orderPayAmount));
                }
                refundWalletBalancePrice = refundWalletPrice;
                if (BigDecimalUtils.greaterZero(refundWalletPrice)) {
                    userWalletDao.addBalance(mallOrder.getUserId(), refundWalletPrice);

                    UserWalletDetail userWalletDetail = new UserWalletDetail();
                    userWalletDetail.setUserId(mallOrder.getUserId());
                    userWalletDetail.setType(WalletDetailTypeEnum.IP_MALL_ORDER_REFUND);
                    userWalletDetail.setAmount(refundWalletPrice);
                    userWalletDetail.setCharge(BigDecimal.ZERO);
                    userWalletDetail.setRealAmount(refundWalletPrice);
                    userWalletDetail.setAfterBalance(userWallet.getBalance().add(refundWalletPrice));
                    userWalletDetail.setBeforeBalance(userWallet.getBalance());
                    userWalletDetail.setIsAdd(Boolean.TRUE);
                    userWalletDetail.setBalanceType(UserBalanceTypeEnum.BALANCE);
                    userWalletDetailDao.insert(userWalletDetail);

                    ExpenditureRecord expenditureRecord = new ExpenditureRecord();
                    expenditureRecord.setUserId(mallOrder.getUserId());
                    expenditureRecord.setAmount(refundWalletPrice);
                    expenditureRecord.setCharge(BigDecimal.ZERO);
                    expenditureRecord.setRealAmount(refundWalletPrice);
                    expenditureRecord.setType(ExpenditureRecordTypeEnum.IP_MALL_REFUND);
                    expenditureRecord.setBeforeBalance(userWallet.getBalance());
                    expenditureRecord.setAfterBalance(userWallet.getBalance().add(refundWalletPrice));
                    expenditureRecord.setRemark(mallOrder.getOrderNo() + ExpenditureRecordTypeEnum.IP_MALL_REFUND.getDescription());
                    expenditureRecordDao.insert(expenditureRecord);

                }
            }
            if (mallOrder.getPayBalancePrice().compareTo(BigDecimal.ZERO) == 1) {
                // 计算红包退款金额
                if (mallOrderRefund.getRefundNum() + mallOrderProduct.getRefundSuccessCount() >= mallOrderProduct.getProductNum()) {
                    // 计算退款差值
                    // 已成功退款 余额金额
                    BigDecimal refundPayBalanceSuccessAmount = refundSuccessList.stream().map(MallOrderRefund::getRefundPayBalancePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                    refundBalancePrice = BigDecimalUtils.subtract(mallOrder.getPayBalancePrice(), refundPayBalanceSuccessAmount);
                } else {
                    // 计算退款
                    refundBalancePrice = BigDecimalUtils.multiplys(mallOrder.getPayBalancePrice(), BigDecimalUtils.divide(mallOrderRefundRefundAmount, orderPayAmount));
                }
                refundWalletBalancePrice = refundBalancePrice;
                if (BigDecimalUtils.greaterZero(refundBalancePrice)) {
                    userWalletDao.addPayBalance(mallOrder.getUserId(), refundBalancePrice);

                    UserWalletDetail userWalletDetail = new UserWalletDetail();
                    userWalletDetail.setUserId(mallOrder.getUserId());
                    userWalletDetail.setType(WalletDetailTypeEnum.IP_MALL_ORDER_REFUND);
                    userWalletDetail.setAmount(refundBalancePrice);
                    userWalletDetail.setCharge(BigDecimal.ZERO);
                    userWalletDetail.setRealAmount(refundBalancePrice);
                    userWalletDetail.setAfterBalance(userWallet.getPayBalance().add(refundBalancePrice));
                    userWalletDetail.setBeforeBalance(userWallet.getPayBalance());
                    userWalletDetail.setIsAdd(Boolean.TRUE);
                    userWalletDetail.setBalanceType(UserBalanceTypeEnum.PAY_BALANCE);
                    userWalletDetailDao.insert(userWalletDetail);

                    ExpenditureRecord expenditureRecord = new ExpenditureRecord();
                    expenditureRecord.setUserId(mallOrder.getUserId());
                    expenditureRecord.setAmount(refundBalancePrice);
                    expenditureRecord.setCharge(BigDecimal.ZERO);
                    expenditureRecord.setRealAmount(refundBalancePrice);
                    expenditureRecord.setType(ExpenditureRecordTypeEnum.IP_MALL_REFUND);
                    expenditureRecord.setBeforeBalance(userWallet.getPayBalance());
                    expenditureRecord.setAfterBalance(userWallet.getPayBalance().add(refundBalancePrice));
                    expenditureRecord.setRemark(mallOrder.getOrderNo() + ExpenditureRecordTypeEnum.IP_MALL_REFUND.getDescription());
                    expenditureRecordDao.insert(expenditureRecord);
                }
            }
            if (mallOrder.getWishBalancePrice().compareTo(BigDecimal.ZERO) == 1) {
                // 计算心愿礼金退款金额
                if (mallOrderRefund.getRefundNum() + mallOrderProduct.getRefundSuccessCount() >= mallOrderProduct.getProductNum()) {
                    // 计算退款差值
                    // 已成功退款 余额金额
                    BigDecimal refundWishBalanceSuccessAmount = refundSuccessList.stream().map(MallOrderRefund::getRefundWishBalancePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                    refundWishBalancePrice = BigDecimalUtils.subtract(mallOrder.getWishBalancePrice(), refundWishBalanceSuccessAmount);
                } else {
                    // 计算退款
                    refundWishBalancePrice = BigDecimalUtils.multiplys(mallOrder.getWishBalancePrice(), BigDecimalUtils.divide(mallOrderRefundRefundAmount, orderPayAmount));
                }
                if (BigDecimalUtils.greaterZero(refundWishBalancePrice)) {
                    userWalletDao.addWishBalance(mallOrder.getUserId(), refundWishBalancePrice);

                    UserWalletDetail userWalletDetail = new UserWalletDetail();
                    userWalletDetail.setUserId(mallOrder.getUserId());
                    userWalletDetail.setType(WalletDetailTypeEnum.IP_MALL_ORDER_REFUND);
                    userWalletDetail.setAmount(refundWishBalancePrice);
                    userWalletDetail.setCharge(BigDecimal.ZERO);
                    userWalletDetail.setRealAmount(refundWishBalancePrice);
                    userWalletDetail.setAfterBalance(userWallet.getWishBalance().add(refundWishBalancePrice));
                    userWalletDetail.setBeforeBalance(userWallet.getWishBalance());
                    userWalletDetail.setIsAdd(Boolean.TRUE);
                    userWalletDetail.setBalanceType(UserBalanceTypeEnum.WISH_BALANCE);
                    userWalletDetailDao.insert(userWalletDetail);

                    ExpenditureRecord expenditureRecord = new ExpenditureRecord();
                    expenditureRecord.setUserId(mallOrder.getUserId());
                    expenditureRecord.setAmount(refundWishBalancePrice);
                    expenditureRecord.setCharge(BigDecimal.ZERO);
                    expenditureRecord.setRealAmount(refundWishBalancePrice);
                    expenditureRecord.setType(ExpenditureRecordTypeEnum.IP_MALL_REFUND);
                    expenditureRecord.setBeforeBalance(userWallet.getWishBalance());
                    expenditureRecord.setAfterBalance(userWallet.getWishBalance().add(refundWishBalancePrice));
                    expenditureRecord.setRemark(mallOrder.getOrderNo() + ExpenditureRecordTypeEnum.IP_MALL_REFUND.getDescription());
                    expenditureRecordDao.insert(expenditureRecord);
                }
            }
            //更新排行榜数据
            if (mallOrder.getPayWalletPrice().compareTo(BigDecimal.ZERO) == 1 || mallOrder.getPayBalancePrice().compareTo(BigDecimal.ZERO) == 1) {
                if (mallOrder.getActivityType() == com.sc.nft.enums.task.ActivityTypeEnum.SALES && !mallOrder.getIsVirtual()) {
                    try {
                        if (refundWalletBalancePrice.compareTo(BigDecimal.ZERO) > 0) {
                            mallUserActivityRankingDetailService.saveOrUpdate(mallOrder.getUserId(), null, refundWalletBalancePrice.negate(), mallOrder.getPayTime());
                            if (MallOrderStatusEnum.FINISH != mallOrder.getStatus() && mallOrder.getStatus() != MallOrderStatusEnum.RECEIPT) {
                                mallUserPropsRewardsDetailService.cancel(mallOrder.getId(), refundWalletBalancePrice);
                            }
                        }
                    } catch (Exception e) {
                        log.error("ranking detail save or update error", e);
                    }
                }
            }
            //支付订单状态
            newPayOrderRecord.setStatus(PayStatusEnum.SUCCESS);

            // 售后单
            mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUND_SUCCES);
            mallOrderRefund.setRefundPayWalletPrice(refundWalletPrice);
            mallOrderRefund.setRefundPayBalancePrice(refundBalancePrice);
            mallOrderRefund.setRefundWishBalancePrice(refundWishBalancePrice);
            mallOrderRefund.updateById();
            // 售后单操作日志
            mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUND_SUCCES, MallRefundStatusEnum.REFUND_SUCCES.getRemark());

            //处理订单商品退款状态
            mallOrderProduct.setRefundSuccessCount(mallOrderProduct.getRefundSuccessCount() + mallOrderRefund.getRefundNum());
            mallOrderProduct.updateById();

            //判断订单是否全部退款
            List<MallOrderProduct> orderProductList = mallOrderProductService.getListByOrderId(mallOrder.getId());
            //商品售后退款成功总数
            int sumRefundSuccessCount = orderProductList.stream().mapToInt(orderProduct -> Objects.isNull(orderProduct.getRefundSuccessCount()) ? 0 : orderProduct.getRefundSuccessCount()).sum();
            //商品购买总数
            int sumProductNum = orderProductList.stream().mapToInt(orderProduct -> Objects.isNull(orderProduct.getProductNum()) ? 0 : orderProduct.getProductNum()).sum();
            if (sumProductNum <= sumRefundSuccessCount) {
                mallOrder.setStatus(MallOrderStatusEnum.CLOSURE);
                mallOrder.updateById();
                MallOrderStatusLog mallOrderStatusLog = new MallOrderStatusLog();
                mallOrderStatusLog.setMallOrderId(mallOrder.getId());
                mallOrderStatusLog.setChangeType(MallOrderStatusEnum.CLOSURE.toString());
                mallOrderStatusLog.setChangeMessage(MallOrderStatusEnum.CLOSURE.getDescription());
                mallOrderStatusLog.setChangeMessage("交易关闭时间");
                mallOrderStatusLog.insert();
            }
            // 总退款金额
            BigDecimal totalRefundSuccessAmount = BigDecimalUtils.add(refundSuccessAmount, mallOrderRefundRefundAmount);
            //收益处理
            List<MallOrderIncome> orderIncomeList = mallOrderIncomeDao.getListByOrderId(mallOrder.getId());
            if (orderIncomeList.size() > 0) {
                //如果退款金额大于等于订单金额，那么收益全部失效
                if (BigDecimalUtils.compareTo(totalRefundSuccessAmount, mallOrder.getRealPrice())) {
                    for (MallOrderIncome mallOrderIncome : orderIncomeList) {
                        mallOrderIncome.setCancelIncomePrice(mallOrderIncome.getIncomeNum());
                        mallOrderIncome.setIncomeStatus(MallOrderIncomeTypeEnum.EXPIRED);
                        mallOrderIncome.setIsEfficient(Boolean.FALSE);
                        mallOrderIncome.updateById();
                    }
                } else {
                    Integer RefundNum = refundSuccessNum + mallOrderRefund.getRefundNum();
                    //只退了一部分商品
                    for (MallOrderIncome mallOrderIncome : orderIncomeList) {
                        MallOrderProduct orderProduct = mallOrderProductService.getOneByOrderIdAndOrderProductId(mallOrderRefund.getOrderId(), mallOrderRefund.getOrderGoodsId());
                        Integer productNum = orderProduct.getProductNum();
                        BigDecimal oldRealIncomePrice = mallOrderIncome.getRealIncomePrice();
                        BigDecimal cancelIncomePrice = BigDecimalUtils.multiplys(oldRealIncomePrice, BigDecimalUtils.divide(RefundNum, productNum)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        BigDecimal realIncomePrice = oldRealIncomePrice.subtract(cancelIncomePrice);
                        //真实到账的收益
                        mallOrderIncome.setRealIncomePrice(realIncomePrice);
                        mallOrderIncome.setIsEfficient(Boolean.TRUE);
                        //失效的收益
                        mallOrderIncome.setCancelIncomePrice(cancelIncomePrice);
                        mallOrderIncome.updateById();
                    }
                }
            }
            // 拼团收益处理
            if (Objects.nonNull(mallOrder.getShareTeamId())) {
                MallShareTeamOrder mallShareTeamOrder = mallShareTeamOrderService.getByOrderId(mallOrder.getShareTeamId(), mallOrder.getId());
                if (Objects.nonNull(mallShareTeamOrder)) {
                    if (BigDecimalUtils.compareTo(totalRefundSuccessAmount, mallOrder.getRealPrice())) {
                        // 全额退款
                        mallShareTeamOrder.setHeadIncome(BigDecimal.ZERO);
                        mallShareTeamOrder.setIsCanIssue(Boolean.FALSE);
                        mallShareTeamOrder.setIsIssue(Boolean.FALSE);
                        mallShareTeamOrder.updateById();
                        // 去除有效订单
                        mallActivityShareTeamService.subValidOrderNumById(mallShareTeamOrder.getActivityShareTeamId(), 1);
                    } else {
                        //只退了一部分商品
                        //订单有效金额
                        BigDecimal orderValidAmount = mallOrder.getRealPrice().subtract(totalRefundSuccessAmount);
                        MallActivityShareTeam mallActivityShareTeam = mallActivityShareTeamService.getById(mallShareTeamOrder.getActivityShareTeamId());
                        MallActivityShare mallActivityShare = mallActivityShareService.getById(mallActivityShareTeam.getActivityShareId());
                        BigDecimal headIncome = orderValidAmount.multiply(mallActivityShare.getRewardPercentage()).setScale(2, BigDecimal.ROUND_DOWN);
                        mallShareTeamOrder.setHeadIncome(headIncome);
                        mallShareTeamOrder.setIsCanIssue(Boolean.TRUE);
                        mallShareTeamOrder.setIsIssue(Boolean.FALSE);
                        mallShareTeamOrder.updateById();
                    }
                }
            }
            MallOrderPushTypeEnum mallOrderPushTypeEnum = null;
            if (MallOrderRefundTypeEnum.ONLY_REFUND == mallOrderRefund.getRefundType()) {
                mallOrderPushTypeEnum = MallOrderPushTypeEnum.ONLY_REFUND_REFUND_SUCCESS;
            } else if (MallOrderRefundTypeEnum.REFUNDS == mallOrderRefund.getRefundType()) {
                mallOrderPushTypeEnum = MallOrderPushTypeEnum.REFUNDS_REFUND_SUCCESS;
            }
            if (Objects.nonNull(mallOrderPushTypeEnum)) {
                MallOrderPushDTO mallOrderPushDTO = new MallOrderPushDTO();
                mallOrderPushDTO.setMallOrderRefund(mallOrderRefund);
                mallOrderPushService.mallOrderPushMessage(mallOrderPushDTO, mallOrderPushTypeEnum);
            }
        } else {
            throw new GlobalRunTimeException("不支持的支付方式");
        }
        mallOrder.updateById();
        newPayOrderRecord.insert();

        try {
            if (StrUtil.isNotBlank(mallOrder.getSupplyOrderNo())) {
                smartSupplyHelper.afterSales(mallOrder, mallOrderRefund.getRefundNum());
            }
        } catch (Exception e) {
            log.info("智慧供应链请求失败:{}", e.getMessage());
        }

    }

    /**
     * 数据处理
     */
    @Override
    public void dataProcessing() {
        // 未申请售后的订单
        List<MallOrder> notApplyList = mallOrderService.getByRefundStatus(MallOrderRefundStatusEnum.NOT_APPLY);
        if (!CollectionUtils.isEmpty(notApplyList)) {
            for (MallOrder mallOrder : notApplyList) {
                mallOrder.setRefundStatus(MallOrderRefundStatusEnum.NEW_NOT_APPLY);
                mallOrder.updateById();
            }
        }
        // 申请售后中的订单
        List<MallOrder> applyingList = mallOrderService.getByRefundStatus(MallOrderRefundStatusEnum.APPLYING);
        if (!CollectionUtils.isEmpty(applyingList)) {
            for (MallOrder mallOrder : applyingList) {
                List<MallOrderProduct> mallOrderProducts = mallOrderProductService.getListByOrderId(mallOrder.getId());
                if (!CollectionUtils.isEmpty(mallOrderProducts)) {
                    MallOrderRefund mallOrderRefund = MallOrderRefund.buildByOldOrder(mallOrder, mallOrderProducts.get(0), MallRefundStatusEnum.APPLYING);
                    mallOrderRefund.insert();
                    mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.APPLYING, "待商家处理");
                    mallOrder.setRefundStatus(MallOrderRefundStatusEnum.NEW_APPLYING);
                    mallOrder.updateById();
                }
            }
        }
        // 拒绝退款的订单
        List<MallOrder> refuseRefundList = mallOrderService.getByRefundStatus(MallOrderRefundStatusEnum.REFUSE_REFUND);
        if (!CollectionUtils.isEmpty(refuseRefundList)) {
            for (MallOrder mallOrder : refuseRefundList) {
                List<MallOrderProduct> mallOrderProducts = mallOrderProductService.getListByOrderId(mallOrder.getId());
                if (!CollectionUtils.isEmpty(mallOrderProducts)) {
                    MallOrderRefund mallOrderRefund = MallOrderRefund.buildByOldOrder(mallOrder, mallOrderProducts.get(0), MallRefundStatusEnum.REFUSE_REFUND);
                    mallOrderRefund.insert();
                    mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUSE_REFUND, MallRefundStatusEnum.REFUSE_REFUND.getDescription());
                    mallOrder.setRefundStatus(MallOrderRefundStatusEnum.NEW_NOT_APPLY);
                    mallOrder.updateById();
                }
            }
        }
        // 退款中的订单
        List<MallOrder> refundingList = mallOrderService.getByRefundStatus(MallOrderRefundStatusEnum.REFUNDING);
        if (!CollectionUtils.isEmpty(refundingList)) {
            for (MallOrder mallOrder : refundingList) {
                List<MallOrderProduct> mallOrderProducts = mallOrderProductService.getListByOrderId(mallOrder.getId());
                if (!CollectionUtils.isEmpty(mallOrderProducts)) {
                    MallOrderRefund mallOrderRefund = MallOrderRefund.buildByOldOrder(mallOrder, mallOrderProducts.get(0), MallRefundStatusEnum.REFUNDING);
                    mallOrderRefund.insert();
                    mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUNDING, "等待到账，退款金额原路退回");
                    mallOrder.setRefundStatus(MallOrderRefundStatusEnum.NEW_APPLYING);
                    mallOrder.updateById();
                }
            }
        }
        // 已退款
        List<MallOrder> refundSuccesList = mallOrderService.getByRefundStatus(MallOrderRefundStatusEnum.REFUND_SUCCES);
        if (!CollectionUtils.isEmpty(refundSuccesList)) {
            for (MallOrder mallOrder : refundSuccesList) {
                List<MallOrderProduct> mallOrderProducts = mallOrderProductService.getListByOrderId(mallOrder.getId());
                if (!CollectionUtils.isEmpty(mallOrderProducts)) {
                    MallOrderRefund mallOrderRefund = MallOrderRefund.buildByOldOrder(mallOrder, mallOrderProducts.get(0), MallRefundStatusEnum.REFUND_SUCCES);
                    mallOrderRefund.insert();
                    mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUND_SUCCES, "退款金额已原路退还到你的账户");
                    mallOrder.setRefundStatus(MallOrderRefundStatusEnum.NEW_APPLYING);
                    mallOrder.updateById();
                }
            }
        }
        // 取消退款
        List<MallOrder> cancelList = mallOrderService.getByRefundStatus(MallOrderRefundStatusEnum.CANCEL);
        if (!CollectionUtils.isEmpty(cancelList)) {
            for (MallOrder mallOrder : cancelList) {
                List<MallOrderProduct> mallOrderProducts = mallOrderProductService.getListByOrderId(mallOrder.getId());
                if (!CollectionUtils.isEmpty(mallOrderProducts)) {
                    MallOrderRefund mallOrderRefund = MallOrderRefund.buildByOldOrder(mallOrder, mallOrderProducts.get(0), MallRefundStatusEnum.CANCEL);
                    mallOrderRefund.insert();
                    mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.CANCEL, MallRefundStatusEnum.CANCEL.getDescription());
                    mallOrder.setRefundStatus(MallOrderRefundStatusEnum.NEW_NOT_APPLY);
                    mallOrder.updateById();
                }
            }
        }
    }

    /**
     * 获取分享团的售后单
     *
     * @param teamId
     * @return
     */
    @Override
    public List<MallOrderRefund> getListByTeamOrder(Long teamId) {
        return mallOrderRefundDao.getListByTeamOrder(teamId);
    }
}
